"""
数据库连接管理
"""

import logging
from datetime import datetime
from motor.motor_asyncio import AsyncIOMotorClient  # pyright: ignore[reportMissingImports]
from pymongo.errors import ConnectionFailure, ServerSelectionTimeoutError  # pyright: ignore[reportMissingImports]
import redis.asyncio as redis  # pyright: ignore[reportMissingImports]
from minio import Minio  # pyright: ignore[reportMissingImports]
from minio.error import S3Error  # pyright: ignore[reportMissingImports]

from app.core.config import settings

# 配置日志
logger = logging.getLogger(__name__)

# 全局数据库客户端
mongodb_client: AsyncIOMotorClient = None
redis_client: redis.Redis = None
minio_client: Minio = None


async def init_database():
    """初始化数据库连接"""
    await init_mongodb()
    await init_redis()
    init_minio()
    # 检查并初始化默认角色
    await check_and_init_default_roles()
    # 初始化版本状态流转相关索引
    try:
        from app.core.init_version_indexes import init_version_transition_indexes
        # get_database 是同步函数，返回 AsyncIOMotorDatabase
        db = get_database()
        if db is not None:
            await init_version_transition_indexes(db)
    except Exception as e:
        import logging
        logger = logging.getLogger(__name__)
        logger.warning(f"初始化版本状态流转索引失败: {str(e)}")
    
    # 初始化需求相关索引
    try:
        from app.core.init_requirement_indexes import init_requirement_indexes
        db = get_database()
        if db is not None:
            await init_requirement_indexes(db)
    except Exception as e:
        import logging
        logger = logging.getLogger(__name__)
        logger.warning(f"初始化需求索引失败: {str(e)}")

async def init_mongodb():
    """初始化MongoDB连接"""
    global mongodb_client
    
    try:
        # 使用配置中的连接URL（已包含认证信息）
        connection_url = settings.MONGODB_URL
        
        # 创建MongoDB客户端
        mongodb_client = AsyncIOMotorClient(
            connection_url,
            serverSelectionTimeoutMS=5000
        )
        
        # 验证连接
        await mongodb_client.admin.command('ping')
        logger.info("MongoDB连接成功")
    except (ConnectionFailure, ServerSelectionTimeoutError) as e:
        logger.error(f"MongoDB连接失败: {e}")
        raise


async def init_redis():
    """初始化Redis连接"""
    global redis_client
    
    try:
        # 构建Redis连接参数
        redis_kwargs = {
            "encoding": "utf-8",
            "decode_responses": True
        }
        
        # 如果有密码，添加密码参数
        if settings.REDIS_PASSWORD:
            redis_kwargs["password"] = settings.REDIS_PASSWORD
        
        redis_client = redis.from_url(
            settings.REDIS_URL,
            **redis_kwargs
        )
        # 验证连接
        await redis_client.ping()
        logger.info("Redis连接成功")
    except Exception as e:
        logger.error(f"Redis连接失败: {e}")
        # Redis连接失败不应该阻止应用启动，只记录错误
        logger.warning("Redis连接失败，将跳过Redis相关功能")
        redis_client = None


def init_minio():
    """初始化MinIO连接"""
    global minio_client
    
    try:
        # 使用更新后的认证信息
        minio_client = Minio(
            settings.MINIO_ENDPOINT,
            access_key=settings.MINIO_ACCESS_KEY,
            secret_key=settings.MINIO_SECRET_KEY,
            secure=settings.MINIO_SECURE
        )
        
        # 检查并创建存储桶
        if not minio_client.bucket_exists(settings.MINIO_BUCKET_NAME):
            minio_client.make_bucket(settings.MINIO_BUCKET_NAME)
            logger.info(f"MinIO存储桶 '{settings.MINIO_BUCKET_NAME}' 已创建")
        
        logger.info("MinIO连接成功")
    except S3Error as e:
        logger.error(f"MinIO连接失败: {e}")
        raise


async def close_mongodb():
    """关闭MongoDB连接"""
    global mongodb_client
    
    if mongodb_client:
        mongodb_client.close()
        logger.info("MongoDB连接已关闭")


async def close_redis():
    """关闭Redis连接"""
    global redis_client
    
    if redis_client:
        await redis_client.close()
        logger.info("Redis连接已关闭")


async def close_database():
    """关闭所有数据库连接"""
    await close_mongodb()
    await close_redis()
    # MinIO 是同步客户端，不需要关闭操作


def get_database():
    """获取MongoDB数据库实例"""
    if not mongodb_client:
        raise ConnectionError("MongoDB客户端未初始化")
    return mongodb_client[settings.MONGODB_DATABASE]


def get_redis():
    """获取Redis客户端实例"""
    # 当Redis不可用时返回None，而不是抛出异常
    return redis_client


def get_minio():
    """获取MinIO客户端实例"""
    if not minio_client:
        raise ConnectionError("MinIO客户端未初始化")
    return minio_client


async def check_and_init_default_roles():
    """检查并初始化默认角色"""
    try:
        # 获取数据库实例
        db = get_database()
        
        # 使用 RoleService 初始化默认角色
        from app.services.role_service import RoleService
        
        result = await RoleService.init_default_roles(db)
        created_count = result.get("created_count", 0)
        updated_count = result.get("updated_count", 0)
        
        if created_count > 0:
            logger.info(f"成功创建 {created_count} 个默认角色")
        if updated_count > 0:
            logger.info(f"成功更新 {updated_count} 个默认角色的权限")
        if created_count == 0 and updated_count == 0:
            logger.info("所有默认角色均已存在且权限已同步")
            
    except Exception as e:
        logger.error(f"检查和初始化默认角色时出错: {e}")